*/ public function register(): array { return [T_FUNCTION]; } /** * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint * @param int $methodPointer */ public function process(File $phpcsFile, $methodPointer): void { $this->minLinesCount = SniffSettingsHelper::normalizeInteger($this->minLinesCount); $this->maxLinesCount = SniffSettingsHelper::normalizeInteger($this->maxLinesCount); if (!FunctionHelper::isMethod($phpcsFile, $methodPointer)) { return; } $tokens = $phpcsFile->getTokens(); $methodEndPointer = array_key_exists('scope_closer', $tokens[$methodPointer]) ? $tokens[$methodPointer]['scope_closer'] : TokenHelper::findNext($phpcsFile, T_SEMICOLON, $methodPointer + 1); $classPointer = ClassHelper::getClassPointer($phpcsFile, $methodPointer); $nextMethodPointer = TokenHelper::findNext($phpcsFile, T_FUNCTION, $methodEndPointer + 1, $tokens[$classPointer]['scope_closer']); if ($nextMethodPointer === null) { return; } $nextMethodAttributeStartPointer = null; $nextMethodDocCommentStartPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $nextMethodPointer); if ( $nextMethodDocCommentStartPointer !== null && $tokens[$tokens[$nextMethodDocCommentStartPointer]['comment_closer']]['line'] + 1 !== $tokens[$nextMethodPointer]['line'] ) { $nextMethodDocCommentStartPointer = null; } else { $nextMethodAttributeStartPointer = TokenHelper::findPrevious( $phpcsFile, T_ATTRIBUTE, $nextMethodPointer - 1, $methodEndPointer, ); if ($nextMethodAttributeStartPointer !== null) { do { $pointerBefore = TokenHelper::findPreviousNonWhitespace( $phpcsFile, $nextMethodAttributeStartPointer - 1, $methodEndPointer, ); if ($tokens[$pointerBefore]['code'] === T_ATTRIBUTE_END) { $nextMethodAttributeStartPointer = $tokens[$pointerBefore]['attribute_opener']; continue; } break; } while (true); } } $nextMethodFirstLinePointer = $tokens[$nextMethodPointer]['line'] === $tokens[$methodEndPointer]['line'] ? TokenHelper::findNextEffective($phpcsFile, $methodEndPointer + 1) : TokenHelper::findFirstTokenOnLine( $phpcsFile, $nextMethodDocCommentStartPointer ?? $nextMethodAttributeStartPointer ?? $nextMethodPointer, ); if (TokenHelper::findNextNonWhitespace($phpcsFile, $methodEndPointer + 1, $nextMethodFirstLinePointer) !== null) { return; } $linesBetween = $tokens[$nextMethodFirstLinePointer]['line'] !== $tokens[$methodEndPointer]['line'] ? $tokens[$nextMethodFirstLinePointer]['line'] - $tokens[$methodEndPointer]['line'] - 1 : null; if ($linesBetween !== null && $linesBetween >= $this->minLinesCount && $linesBetween <= $this->maxLinesCount) { return; } if ($this->minLinesCount === $this->maxLinesCount) { $errorMessage = $this->minLinesCount === 1 ? 'Expected 1 blank line after method, found %3$d.' : 'Expected %2$d blank lines after method, found %3$d.'; } else { $errorMessage = 'Expected %1$d to %2$d blank lines after method, found %3$d.'; } $fix = $phpcsFile->addFixableError( sprintf($errorMessage, $this->minLinesCount, $this->maxLinesCount, $linesBetween ?? 0), $methodPointer, self::CODE_INCORRECT_LINES_COUNT_BETWEEN_METHODS, ); if (!$fix) { return; } $phpcsFile->fixer->beginChangeset(); if ($linesBetween === null) { FixerHelper::add( $phpcsFile, $methodEndPointer, $phpcsFile->eolChar . str_repeat($phpcsFile->eolChar, $this->minLinesCount) . IndentationHelper::getIndentation( $phpcsFile, TokenHelper::findFirstNonWhitespaceOnLine($phpcsFile, $methodPointer), ), ); FixerHelper::removeBetween($phpcsFile, $methodEndPointer, $nextMethodFirstLinePointer); } elseif ($linesBetween > $this->maxLinesCount) { FixerHelper::add( $phpcsFile, $methodEndPointer, str_repeat($phpcsFile->eolChar, $this->maxLinesCount + 1), ); $firstPointerOnNextMethodLine = TokenHelper::findFirstTokenOnLine($phpcsFile, $nextMethodFirstLinePointer); FixerHelper::removeBetween($phpcsFile, $methodEndPointer, $firstPointerOnNextMethodLine); } else { FixerHelper::add( $phpcsFile, $methodEndPointer, str_repeat($phpcsFile->eolChar, $this->minLinesCount - $linesBetween), ); } $phpcsFile->fixer->endChangeset(); } }